package com.tutu.service.impl;

import com.tutu.controller.CommonsController;
import com.tutu.controller.backend.DataController;
import com.tutu.core.Constant;
import com.tutu.core.api.DataApiUrls;
import com.tutu.core.api.DeviceApiUrls;
import com.tutu.core.api.DeviceShareApiUrls;
import com.tutu.core.api.DeviceSummaryApiUrls;
import com.tutu.entity.vo.BaseCodeVo;
import com.tutu.service.*;
import com.tutu.utils.*;
import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONArray;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * UserServiceImpl
 */
@Service
@Slf4j
public class DeviceServiceImpl implements DeviceService {

    @Autowired
    CompanyService companyService;

    @Autowired
    CodeDictService codeDictService;

    @Autowired
    DeviceDataService deviceDataService;

    @Autowired
    AlarmMessageService alarmMessageService;

    @Override
    public Map<String, Object> pageByParams(Integer loginCompanyId, Integer companyId, String keyWord, Integer deviceType, Integer stateType, Integer pageNum, Integer pageSize) {
        int finallyCompanyId = 0;

        if (null == loginCompanyId) {
            if (null != companyId) finallyCompanyId = companyId;
        } else {
            if (null != companyId) {
                finallyCompanyId = companyId;
            } else {
                finallyCompanyId = loginCompanyId;
            }
        }

        return HttpRequestUtil.getOnlyData(DeviceApiUrls.base_prefix + DeviceApiUrls.page, "keyWord=" + UnicodeUtil.unicodeEncode(keyWord) + "&deviceType=" + deviceType + "&stateType=" + stateType + "&pageNum=" + pageNum + "&pageSize=" + pageSize + (finallyCompanyId > 0 ? ("&companyId=" + finallyCompanyId) : ""));
    }

    @Override
    public Map<String, Object> pageByParams(String deviceCode, Integer type, String searchDate, String keyWord, Integer pageNum, Integer pageSize) {
        if (BaseUtil.isBlank(deviceCode)) return BaseUtil.defaultPageErrorInfo();

        Map<String, Object> dataMap = HttpRequestUtil.getOnlyData(DataApiUrls.base_prefix + DataApiUrls.pageByBackendParams, "keyWord=" + UnicodeUtil.unicodeEncode(keyWord) + "&pageNum=" + pageNum + "&pageSize=" + pageSize + "&deviceCode=" + deviceCode + "&type=" + type + "&searchDate=" + (BaseUtil.isBlank(searchDate) ? DateUtils.getTime() : searchDate));

        List<Map<String, Object>> list = new ArrayList<>();
        Map<String, Object> map;
        Map<String, Object> temp;
        String code;
        Map<String, Object> infoMap;
        String key;

        for (Object o : JSONArray.fromObject(dataMap.get("content"))) {
            map = JsonUtil.json2Map(o);

            if (map.size() == 0) continue;

            infoMap = new HashMap<>();

            for (Object obj : JSONArray.fromObject(map.get("valueList"))) {
                temp = JsonUtil.json2Map(obj);

                code = temp.get("code") + "";

                key = deviceCode + "_" + type + "_" + code;

                if (temp.get("status").equals(0)) {
                    if (DataController.deviceCodeDictStatusMap.containsKey(key)) {
                        if (DataController.deviceCodeDictStatusMap.get(key).equals(0)) continue;
                    } else {
                        DataController.deviceCodeDictStatusMap.put(key, 0);
                        continue;
                    }
                }

                DataController.deviceCodeDictStatusMap.put(key, 1);

                infoMap.put(code, (code.equals("CP_DataTime") ? DateUtils.changeStrTime(temp.get("value").toString()) + "" : temp.get("value") + ""));
            }

            list.add(infoMap);
        }

        dataMap.put("data", list);
        dataMap.put("iTotalRecords", dataMap.get("total"));
        dataMap.put("iTotalDisplayRecords", dataMap.get("total"));

        return dataMap;
    }

    @Override
    public Map<String, Object> pageByParams(Integer companyId, Integer deviceId, Integer pageNum, Integer pageSize) {
        return HttpRequestUtil.getOnlyData(DeviceShareApiUrls.base_prefix + DeviceShareApiUrls.page, "pageNum=" + pageNum + "&pageSize=" + pageSize + "&companyId=" + companyId + "&deviceId=" + deviceId);
    }

    @Override
    public Map<String, Object> getInfoById(Integer id) {
        Map<String, Object> map = new HashMap<>();

        for (List<Map<String, Object>> list : CommonsController.baseDeviceList.values())
            for (Map<String, Object> tempMap : list)
                if (tempMap.get("id").equals(id)) {
                    map = tempMap;

                    break;
                }

        return map;
    }

    @Override
    public Map<String, Object> getInfoByCode(String deviceCode) {
        Map<String, Object> map = new HashMap<>();

        for (List<Map<String, Object>> list : CommonsController.baseDeviceList.values())
            for (Map<String, Object> tempMap : list)
                if (tempMap.get("code").equals(deviceCode)) {
                    map = tempMap;

                    break;
                }

        if (map.size() > 0) map.put("company", JsonUtil.json2Map(map.get("company")));

        return map;
    }

    @Override
    public Map<String, Object> saveInfo(HttpServletRequest request, Integer id, Integer deviceType, Integer stateType, Integer companyId, String name, String code, Integer showIndex) {
        LogInfoServiceImpl.saveLogInfo(request, "编辑设备信息，ID：" + id + "，设备类型：" + deviceType + "，设备类别：" + stateType + "，公司ID：" + companyId + "，设备名称：" + name + "，设备编码：" + code + "，设备序号：" + showIndex);

        String url = DeviceApiUrls.base_prefix + DeviceApiUrls.update;

        if (null == id) url = DeviceApiUrls.base_prefix + DeviceApiUrls.create;

        Map<String, Object> map = HttpRequestUtil.getCompleteData(url, "id=" + id + "&name=" + UnicodeUtil.unicodeEncode(name) + "&code=" + code + "&deviceType=" + deviceType + "&stateType=" + stateType + "&companyId=" + companyId + "&showIndex=" + showIndex);

        loadCacheData(request);

        return map;
    }

    @Override
    public Map<String, Object> deleteById(HttpServletRequest request, Integer companyId, Integer id) {
        LogInfoServiceImpl.saveLogInfo(request, "删除设备信息，ID：" + id + "，公司ID：" + companyId);

        Map<String, Object> map = HttpRequestUtil.getCompleteData(DeviceApiUrls.base_prefix + DeviceApiUrls.delete, "id=" + id);

        loadCacheData(request);

        return map;
    }

    @Override
    public Map<String, Object> batchDel(HttpServletRequest request, Integer companyId, String ids) {
        LogInfoServiceImpl.saveLogInfo(request, "批量删除设备信息，IDS：" + ids + "，公司ID：" + companyId);

        Map<String, Object> map = HttpRequestUtil.getCompleteData(DeviceApiUrls.base_prefix + DeviceApiUrls.batchDel, "ids=" + ids);

        loadCacheData(request);

        return map;
    }

    @Override
    public List<BaseCodeVo> findListByCompanyId(Integer companyId) {
        List<BaseCodeVo> list = new ArrayList<>();
        Map<String, Object> map;

        if (null != companyId) {
            if (CommonsController.baseDeviceList.containsKey(companyId + "")) for (Object o : CommonsController.baseDeviceList.get(companyId + "")) {
                map = JsonUtil.json2Map(o);

                if (map.containsKey("id")) list.add(new BaseCodeVo(Integer.parseInt(map.get("id") + ""), map.get("code") + "", map.get("name") + ""));
            }
        } else {
            for (List<Map<String, Object>> o : CommonsController.baseDeviceList.values())
                for (Object obj : JSONArray.fromObject(o)) {
                    map = JsonUtil.json2Map(obj);

                    if (map.containsKey("id")) list.add(new BaseCodeVo(Integer.parseInt(map.get("id") + ""), map.get("code") + "", map.get("name") + ""));
                }
        }

        return list;
    }

    @Override
    public Map<String, Object> saveForward(HttpServletRequest request, Integer deviceId, String address, String port) {
        LogInfoServiceImpl.saveLogInfo(request, "添加设备转发，设备ID：" + deviceId + "，转发IP：" + address + "，转发端口：" + port);

        return HttpRequestUtil.getCompleteData(DeviceShareApiUrls.base_prefix + DeviceShareApiUrls.create, "deviceId=" + deviceId + "&address=" + address + "&port=" + port);
    }

    @Override
    public Map<String, Object> batchSaveForward(HttpServletRequest request, String address, String port) {
        LogInfoServiceImpl.saveLogInfo(request, "批量添加设备转发，转发IP：" + address + "，转发端口：" + port);

        return HttpRequestUtil.getCompleteData(DeviceShareApiUrls.base_prefix + DeviceShareApiUrls.batchCreate, "address=" + address + "&port=" + port);
    }

    @Override
    public Map<String, Object> delForward(HttpServletRequest request, Integer id) {
        LogInfoServiceImpl.saveLogInfo(request, "删除设备转发，设备ID：" + id);

        return HttpRequestUtil.getCompleteData(DeviceShareApiUrls.base_prefix + DeviceShareApiUrls.delete, "id=" + id);
    }

    @Override
    public Map<String, Object> batchUpdateStatus(HttpServletRequest request, String deviceCode, String type, Integer status) {
        LogInfoServiceImpl.saveLogInfo(request, "批量更新设备参数显示状态，设备编码：" + deviceCode + "，数据类型：" + type + "，状态：" + status);

        Map<String, Object> map = HttpRequestUtil.getCompleteData(DataApiUrls.base_prefix + DataApiUrls.batchUpdateDeviceCodeStatus, "deviceCode=" + deviceCode + "&type=" + type + "&status=" + status);

        codeDictService.loadCacheData();

        return map;
    }

    @Override
    public Map<String, Object> updateDeviceEmission(HttpServletRequest request, String deviceCode, String codeNameStr, String countStr, String dayStr) {
        LogInfoServiceImpl.saveLogInfo(request, "修改设备排放因子信息，设备编码：" + deviceCode + "，因子名称：" + codeNameStr + "，排放量：" + countStr + "，计算周期：" + dayStr);

        return HttpRequestUtil.getCompleteData(DeviceSummaryApiUrls.base_prefix + DeviceSummaryApiUrls.updateDeviceEmission, "deviceCode=" + deviceCode + "&codeNameStr=" + UnicodeUtil.unicodeEncode(codeNameStr) + "&countStr=" + countStr + "&dayStr=" + dayStr);
    }

    @Override
    public Map<String, Object> syncData(HttpServletRequest request) {
        LogInfoServiceImpl.saveLogInfo(request, "同步设备信息");

        Map<String, Object> map;

        if (CommonsController.needSync("device")) {
            map = HttpRequestUtil.getSyncData(5);
        } else {
            map = BaseUtil.defaultErrorInfo(null);
        }

        return map;
    }

    @Override
    public Map<String, Object> syncDeviceShare(HttpServletRequest request) {
        LogInfoServiceImpl.saveLogInfo(request, "同步设备转发信息");

        Map<String, Object> map;

        if (CommonsController.needSync("deviceShare")) {
            map = HttpRequestUtil.getSyncData(6);
        } else {
            map = BaseUtil.defaultErrorInfo(null);
        }

        return map;
    }

    @Override
    public Map<String, Object> syncDeviceUser(HttpServletRequest request) {
        LogInfoServiceImpl.saveLogInfo(request, "同步设备用户关联信息");

        Map<String, Object> map;

        if (CommonsController.needSync("deviceUser")) {
            map = HttpRequestUtil.getSyncData(7);
        } else {
            map = BaseUtil.defaultErrorInfo(null);
        }

        return map;
    }

    @Override
    public Map<String, Object> iWebPageByParams(String openId, Integer projectId, Integer type, String startTime, String endTime, Integer pageNum, Integer pageSize) {
        return HttpRequestUtil.getOnlyData(DataApiUrls.base_prefix + DataApiUrls.pagePlus, "pageNum=" + pageNum + "&pageSize=" + pageSize + "&openId=" + openId + "&projectId=" + projectId + "&type=" + type + "&startTime=" + startTime + "&endTime=" + endTime);
    }

    @Override
    public List<Map<String, Object>> iFindListByParams(Integer projectId, Integer deviceId, String dataCode, Integer type, String startTime, String endTime) {
        return null;
    }

    @Override
    public List<Map<String, Object>> findDeviceEmissionInfo(String deviceCode) {
        return HttpRequestUtil.getListData(DeviceSummaryApiUrls.base_prefix + DeviceSummaryApiUrls.findDeviceEmissionInfo, "deviceCode=" + deviceCode);
    }

    @Override
    public void loadCacheData(HttpServletRequest request) {
        CommonsController.executorService.submit(() -> {
            List<Map<String, Object>> list = new ArrayList<>();

            if (null != request) {
                String companyId = request.getSession().getAttribute(Constant.CURRENT_LOGIN_COMPANY_ID) + "";

                if (BaseUtil.isNotBlank(companyId)) {
                    CommonsController.baseDeviceList.remove(companyId);

                    for (Object o : HttpRequestUtil.getListData(DeviceApiUrls.base_prefix + DeviceApiUrls.findListByCompanyId, "companyId=" + companyId))
                        list.add(JsonUtil.json2Map(o));

                    if (list.size() > 0) CommonsController.baseDeviceList.put(companyId, list);
                }
            } else {
                CommonsController.baseDeviceList.clear();

                for (Map<String, Object> companyMap : CommonsController.baseCompanyList) {
                    if (!companyMap.containsKey("id")) continue;

                    list = new ArrayList<>();

                    for (Object o : HttpRequestUtil.getListData(DeviceApiUrls.base_prefix + DeviceApiUrls.findListByCompanyId, "companyId=" + companyMap.get("id")))
                        list.add(JsonUtil.json2Map(o));

                    if (list.size() > 0) CommonsController.baseDeviceList.put(companyMap.get("id") + "", list);
                }
            }

            if (CommonsController.baseDeviceList.size() == 0) {
                try {
                    log.info("设备信息请求失败，3秒后自动重试...");

                    Thread.sleep(3000L);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                loadCacheData(request);
            }

            log.info("共计加载" + CommonsController.baseDeviceList.values().size() + "个公司所属设备信息...");
        });
    }

    @Override
    public Map<String, Object> updateShowStatus(HttpServletRequest request, String deviceCode, Integer type) {
        LogInfoServiceImpl.saveLogInfo(request, "更新设备展示状态，设备编码：" + deviceCode + "，状态：" + type);

        return HttpRequestUtil.getCompleteData(DeviceApiUrls.base_prefix + DeviceApiUrls.updateDeviceShowStatus, "deviceCode=" + deviceCode + "&type=" + type);
    }

    @Override
    public Map<String, Object> updateZeroAlarmStatus(HttpServletRequest request, String deviceCode, Integer status) {
        LogInfoServiceImpl.saveLogInfo(request, "更新设备零值预警状态，设备编码：" + deviceCode + "，状态：" + status);

        return HttpRequestUtil.getCompleteData(DeviceApiUrls.base_prefix + DeviceApiUrls.updateDeviceZeroAlarmStatus, "deviceCode=" + deviceCode + "&status=" + status);
    }

    @Override
    public Map<String, Object> updateAlarmStatus(HttpServletRequest request, String deviceCode, Integer status) {
        LogInfoServiceImpl.saveLogInfo(request, "更新设备预警状态，设备编码：" + deviceCode + "，状态：" + status);

        return HttpRequestUtil.getCompleteData(DeviceApiUrls.base_prefix + DeviceApiUrls.updateDeviceAlarmStatus, "deviceCode=" + deviceCode + "&status=" + status);
    }

    @Override
    public Map<String, Object> refreshDeviceStaticData(HttpServletRequest request) {
        LogInfoServiceImpl.saveLogInfo(request, "初始化设备汇总数据");

        return HttpRequestUtil.getCompleteData(DeviceSummaryApiUrls.base_prefix + DeviceSummaryApiUrls.refreshInfo, "");
    }

    @Override
    public void noticeDeviceStatusInfo(String deviceName, String userOpenId, Integer type) {
        String content;

        if (type.equals(Constant.CHECK_STATUS_SUCCESS)) {
            content = "设备已上线，数据功能已恢复";
        } else {
            content = "设备已下线，数据功能已停止";
        }

        WxMsgPushUtil.receiveMsg("设备在线状态变更", content, deviceName, System.currentTimeMillis(), userOpenId);
    }
}